/*
draw Interface;
work with matrix;

 0 100  %
 1 000 %%%
 2 000  %      %
 3 000 ***********   3333333
 4 010 *    %  % *
 5 000 *   %%%%%%*
 6 000 *    %    *
 7 000 *   %%%   *
 8 000 *         *
 9 000 *         *
10 000 *         *
11 000 *         *
12 001 *       % *
13 000 *      %%%*
14 000 *       % *
15 000 *      %%%*
16 020 *    @    *
17 000 *   @@@   *   BOARD_ROW = 18
18 000 *    @    *
19 000 *   @@@   *
20 000 ***********

*/

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#define BOARD_ROW 21
#define BOARD_COL 11
#define MY_CAR_STYLE '@'
#define MOB_CAR_STYLE '%'
#define BOARD_STYLE '*'
#define LIFE_STYLE '$'
#define STREET_STYLE ' '
#define SPOT_0 2
#define SPOT_1 5
#define SPOT_2 8
#define LIFE_BEGIN 5
#define TOP_SPEED 1
#define SPEED_PER_LEVER 1
#define START_SPEED 15
#define SCORE 10
#define CAR_PER_LEVEL 20

//--------------------- Interface ------------------------------------------------
void MakeAPoint(char matrixInterface[BOARD_ROW][BOARD_COL], int x, int y, char style)
{
    if(x > 3 && x < BOARD_ROW-1 && y > 0 && y < BOARD_COL-1)
        matrixInterface[x][y] = style;
}

void MakeCar(char matrixInterface[BOARD_ROW][BOARD_COL], int x, int y, char style)
{
    switch (y)
    {
    case 0:
        y = SPOT_0;
        break;
    case 1:
        y = SPOT_1;
        break;
    case 2:
        y = SPOT_2;
        break;

    }
    MakeAPoint(matrixInterface,x,y,style);
    MakeAPoint(matrixInterface,x+1,y,style);
    MakeAPoint(matrixInterface,x+2,y,style);
    MakeAPoint(matrixInterface,x+3,y,style);

    MakeAPoint(matrixInterface,x+1,y-1,style);
    MakeAPoint(matrixInterface,x+1,y+1,style);
    MakeAPoint(matrixInterface,x+3,y-1,style);
    MakeAPoint(matrixInterface,x+3,y+1,style);
}

void GetStringLife( int life, char stringLife[])
{

    int i;

    if (life >LIFE_BEGIN)return;
    for (i = 0; i<life; i++)
    {
        stringLife[i] = LIFE_STYLE;
    }
    stringLife[life] = '\0';
}

void DrawBoard(char matrixInterface[BOARD_ROW][BOARD_COL])
{
    int i,j;

    for(i = 3; i< BOARD_ROW; i++)
    {
        matrixInterface[i][0] = BOARD_STYLE;
        matrixInterface[i][BOARD_COL-1] = BOARD_STYLE;
    }
    //
    for(j = 1; j< (BOARD_COL-1) ; j++)
    {
        matrixInterface[3][j] = BOARD_STYLE;
        matrixInterface[BOARD_ROW-1][j] = BOARD_STYLE;
    }

    for(i = 4; i< BOARD_ROW - 1 ; i++)
    {
        for (j = 1; j< (BOARD_COL-1) ; j++)
        {
            matrixInterface[i][j] = STREET_STYLE;
        }
    }
}

void DrawInterface(int matrix[BOARD_ROW][3], int life, int score, int level)
{

    char matrixInterface[BOARD_ROW][BOARD_COL];
    int i,j;

    DrawBoard(matrixInterface);
    for (i = 0; i< (BOARD_ROW) ; i++)
        for (j = 0; j<3 ; j++)
        {
            if ( matrix[i][j] == 1)
            {
                MakeCar(matrixInterface,i,j,MOB_CAR_STYLE);
            }
            else if ( matrix[i][j] == 2)
                MakeCar(matrixInterface, i, j,MY_CAR_STYLE);
        }


    char stringLife[10];
    GetStringLife(life, stringLife);

    printf(" Life : %s   Score: %d\n", stringLife, score);
    printf(" Level : %d\n", level);

    for(i = 3; i< BOARD_ROW; i++)
    {
        for(j = 0; j< BOARD_COL; j++)
        {
            printf("%c", matrixInterface[i][j]);
        }
        printf("\n");
    }
}

//---------------------/Interface ----------------------------------------------------


//---------------------- Core --------------------------------------------------------
void CreateMatrix(int matrix[BOARD_ROW][3])
{
    int i,j;
    for (i= 0; i< BOARD_ROW; i++)
    {
        for (j= 0; j< 3; j++)
        {
            matrix[i][j] = 0;
        }
    }
    matrix[BOARD_ROW-5][1] = 2;
}

void CarsMoving(int matrix[BOARD_ROW][3], int spot)
{
    int i,j;

    for (i = BOARD_ROW-1; i > 0; i--)
    {
        for (j = 0; j<3 ; j++)
        {
            matrix[i][j] = matrix[i-1][j];
        }
    }
    matrix[0][0] = 0;
    matrix[0][1] = 0;
    matrix[0][2] = 0;

    matrix[BOARD_ROW -5][spot] = 2;
    matrix[BOARD_ROW -4][spot] = 0;
}

int RandomCarAppearType2()
{
    srand (time(NULL));
    return rand()%3;
}

int RandomCarAppearType1()
{
    srand (time(NULL));
    return rand()%2;
}

int RandomCarAppearType3()
{
    srand (time(NULL));
    return (rand()%2+1);
}


void ScoreCalculate(int matrix[BOARD_ROW][3],int *score)
{
    if (( matrix[BOARD_ROW - 5][0] == 1)||( matrix[BOARD_ROW - 5][1] == 1)||( matrix[BOARD_ROW - 5][2] == 1))
        *score += SCORE;
}

void KbHitted(int matrix[BOARD_ROW][3], int* spot, int* isRestart, int* isQuit)
{
    char key;
    key = getch();

    switch (key)
    {
    case 75:
    {
        if (*spot == 1)
        {
            *spot = 0;
            matrix[BOARD_ROW - 5 ][1] = 0;
            matrix[BOARD_ROW - 5 ][0] = 2;
        }
        if (*spot == 2)
        {
            *spot = 1;
            matrix[BOARD_ROW - 5 ][2] = 0;
            matrix[BOARD_ROW - 5 ][1] = 2;
        }
        break;
    }
    case 77:
    {
        if (*spot == 1)
        {
            *spot = 2;
            matrix[BOARD_ROW - 5 ][1] = 0;
            matrix[BOARD_ROW - 5 ][2] = 2;
        }
        if (*spot == 0)
        {
            *spot = 1;
            matrix[BOARD_ROW - 5 ][0] = 0;
            matrix[BOARD_ROW - 5 ][1] = 2;
        }
        break;
    }
    case 'r':
    {
        *isRestart = 1;
        break;
    }
    case 'x':
    {
        *isQuit = 1;
        break;
    }
    }
}

int IsHitted(int matrix[BOARD_ROW][3], int spot )
{
    int i;
    for (i = BOARD_ROW - 8; i< BOARD_ROW-1; i++)
        if (matrix[i][spot] == 1)
        {
            return 1;
        }
    return 0;
}

void GameStart(int life, int score, int level)
{

    int matrix[BOARD_ROW][3];
    CreateMatrix(matrix);
    int block;
    int gameTime = 0;
    int spot = 1;
    int space = 1;
    int mobSpot1, mobSpot2 = -1, mobSpot3 = -1;
    int randomType;
    int isRestart = 0, isQuit = 0;

    while (1)
    {
        DrawInterface (matrix, life, score, level);
        //OutputMatrix(matrix);
        int speed = START_SPEED - level +1;
        gameTime +=1;
        if (gameTime % speed == 0)
        {
            CarsMoving(matrix, spot);
            ScoreCalculate( matrix, &score);
        }

        if ((gameTime % (speed * 5)) == 0)
        {

            srand (time(NULL));
            //printf("---------------------------------%d", rand()%2);
            //_sleep(1000);
            //getch();

            int probability;
            probability =  rand()%100;
            if ( probability <70 || space == 1)
            {
                if (mobSpot2 == 1 && mobSpot3 == 0)
                {
                    mobSpot1 = RandomCarAppearType1();
                    matrix[0][mobSpot1] = 1;
                }
                else if (mobSpot2 == 1 && mobSpot3 == 2)
                {
                    mobSpot1 = RandomCarAppearType3();
                    matrix[0][mobSpot1] = 1;
                }

                else
                {
                    mobSpot1 = RandomCarAppearType2();
                    matrix[0][mobSpot1] = 1;
                }


                if ( mobSpot2 != 1)
                {
                    mobSpot3 = mobSpot2;
                }
                mobSpot2 = mobSpot1;



                space = 0;
            }
            else space = 1;

        }

        if (kbhit())
        {
            KbHitted(matrix, &spot, &isRestart, &isQuit);
        }

        if ( IsHitted( matrix , spot ) )
        {
            if (life == 1)
            {
                main();
            }
            else
            {
                GameStart(life - 1 , score, level);
            }
        }

        if (isRestart)
        {
            main();
        }

        if (isQuit)
        {
            return;
        }

        if (level > 14 )
        {
            level = 1;
        }
        if (gameTime == speed * 5 * CAR_PER_LEVEL)
        {
            level ++;
            gameTime = 0;
        }


        _sleep(10);
        system("cls");
    }
}

//---------------------- /Core -------------------------------------------------------


void main()
{
    GameStart(LIFE_BEGIN, 0, 1);
}




